package cn.stylefeng.roses.ent.saas.factory;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.stylefeng.roses.ent.saas.pojo.dto.MenuAndOptionsDTO;
import cn.stylefeng.roses.kernel.rule.enums.YesOrNotEnum;
import cn.stylefeng.roses.kernel.saas.api.callback.TenantMenuAndOptionsCollectorApi;
import cn.stylefeng.roses.kernel.sys.modular.menu.entity.SysMenu;
import cn.stylefeng.roses.kernel.sys.modular.menu.entity.SysMenuOptions;
import cn.stylefeng.roses.kernel.sys.modular.menu.service.SysMenuOptionsService;
import cn.stylefeng.roses.kernel.sys.modular.menu.service.SysMenuService;
import cn.stylefeng.roses.kernel.sys.modular.org.entity.HrOrganization;
import cn.stylefeng.roses.kernel.sys.modular.position.entity.HrPosition;
import cn.stylefeng.roses.kernel.sys.modular.role.entity.SysRole;
import cn.stylefeng.roses.kernel.sys.modular.role.entity.SysRoleLimit;
import cn.stylefeng.roses.kernel.sys.modular.role.entity.SysRoleMenu;
import cn.stylefeng.roses.kernel.sys.modular.role.entity.SysRoleMenuOptions;
import cn.stylefeng.roses.kernel.sys.modular.role.enums.RoleLimitTypeEnum;
import cn.stylefeng.roses.kernel.sys.modular.user.entity.SysUser;
import cn.stylefeng.roses.kernel.sys.modular.user.entity.SysUserOrg;
import cn.stylefeng.roses.kernel.sys.modular.user.entity.SysUserRole;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 租户的关联信息创建工厂
 *
 * @author fengshuonan
 * @since 2023/9/7 11:51
 */
public class TenantLinkFactory {

    /**
     * 创建租户的组织机构关联信息
     *
     * @author fengshuonan
     * @since 2023/9/7 11:51
     */
    public static SysUserOrg createUserOrgLink(SysUser sysUser, HrOrganization hrOrganization, HrPosition hrPosition) {

        SysUserOrg sysUserOrg = new SysUserOrg();

        sysUserOrg.setUserId(sysUser.getUserId());
        sysUserOrg.setOrgId(hrOrganization.getOrgId());
        sysUserOrg.setPositionId(hrPosition.getPositionId());
        sysUserOrg.setMainFlag(YesOrNotEnum.Y.getCode());

        return sysUserOrg;
    }

    /**
     * 创建用户角色的关联信息
     *
     * @author fengshuonan
     * @since 2023/9/7 11:54
     */
    public static SysUserRole createUserRoleLink(SysUser sysUser, SysRole sysRole) {

        SysUserRole sysUserRole = new SysUserRole();

        sysUserRole.setUserId(sysUser.getUserId());
        sysUserRole.setRoleId(sysRole.getRoleId());

        return sysUserRole;
    }

    /**
     * 获取租户初始化的默认的菜单和功能的集合
     *
     * @author fengshuonan
     * @since 2023/9/7 14:10
     */
    public static MenuAndOptionsDTO getTenantMenuAndOptions(Long roleId) {

        SysMenuService sysMenuService = SpringUtil.getBean(SysMenuService.class);
        SysMenuOptionsService sysMenuOptionsService = SpringUtil.getBean(SysMenuOptionsService.class);

        // 通过callback接口获取所有应该初始化的菜单id和OptionsId
        List<Long> menuIds = new ArrayList<>();
        List<Long> menuOptionsIds = new ArrayList<>();
        Map<String, TenantMenuAndOptionsCollectorApi> tenantMenuAndOptionsCollectorApiMap = SpringUtil.getBeansOfType(TenantMenuAndOptionsCollectorApi.class);
        for (TenantMenuAndOptionsCollectorApi tenantMenuAndOptionsCollectorApi : tenantMenuAndOptionsCollectorApiMap.values()) {
            menuIds.addAll(tenantMenuAndOptionsCollectorApi.getMenuIds());
            menuOptionsIds.addAll(tenantMenuAndOptionsCollectorApi.getOptionIds());
        }

        if (ObjectUtil.isEmpty(menuIds)) {
            return new MenuAndOptionsDTO();
        }

        // 获取菜单对应的appId（为了后面插入冗余字段）
        LambdaQueryWrapper<SysMenu> sysMenuLambdaQueryWrapper = new LambdaQueryWrapper<>();
        sysMenuLambdaQueryWrapper.in(SysMenu::getMenuId, menuIds);
        sysMenuLambdaQueryWrapper.select(SysMenu::getMenuId, SysMenu::getAppId);
        List<SysMenu> menuConditions = sysMenuService.list(sysMenuLambdaQueryWrapper);

        // 获取optionId对应的appId和菜单id（为了后面插入冗余字段）
        LambdaQueryWrapper<SysMenuOptions> sysMenuOptionsLambdaQueryWrapper = new LambdaQueryWrapper<>();
        sysMenuOptionsLambdaQueryWrapper.in(SysMenuOptions::getMenuOptionId, menuOptionsIds);
        sysMenuOptionsLambdaQueryWrapper.select(SysMenuOptions::getMenuOptionId, SysMenuOptions::getAppId, SysMenuOptions::getMenuId);
        List<SysMenuOptions> menuOptionsConditions = sysMenuOptionsService.list(sysMenuOptionsLambdaQueryWrapper);

        // 转化为角色绑定的角色菜单和角色功能
        List<SysRoleMenu> roleMenuList = new ArrayList<>();
        List<SysRoleMenuOptions> roleOptionsList = new ArrayList<>();
        List<SysRoleLimit> roleLimitList = new ArrayList<>();

        for (Long menuId : menuIds) {
            SysRoleMenu sysRoleMenu = new SysRoleMenu();
            sysRoleMenu.setRoleId(roleId);

            // 获取冗余的appId
            for (SysMenu menuCondition : menuConditions) {
                if (menuCondition.getMenuId().equals(menuId)) {
                    sysRoleMenu.setAppId(menuCondition.getAppId());
                    break;
                }
            }

            sysRoleMenu.setMenuId(menuId);
            roleMenuList.add(sysRoleMenu);

            // 【2023年9月8日】增加角色绑定的菜单限制
            SysRoleLimit sysRoleLimit = new SysRoleLimit();
            sysRoleLimit.setRoleId(roleId);
            sysRoleLimit.setLimitType(RoleLimitTypeEnum.MENU.getCode());
            sysRoleLimit.setBusinessId(menuId);
            roleLimitList.add(sysRoleLimit);
        }

        for (Long menuOptionsId : menuOptionsIds) {
            SysRoleMenuOptions sysRoleMenuOptions = new SysRoleMenuOptions();
            sysRoleMenuOptions.setRoleId(roleId);

            // 获取冗余的appId和menuId
            for (SysMenuOptions menuOptionsCondition : menuOptionsConditions) {
                if (menuOptionsCondition.getMenuOptionId().equals(menuOptionsId)) {
                    sysRoleMenuOptions.setAppId(menuOptionsCondition.getAppId());
                    sysRoleMenuOptions.setMenuId(menuOptionsCondition.getMenuId());
                    break;
                }
            }

            sysRoleMenuOptions.setMenuOptionId(menuOptionsId);
            roleOptionsList.add(sysRoleMenuOptions);

            // 【2023年9月8日】增加角色绑定的功能限制
            SysRoleLimit sysRoleLimit = new SysRoleLimit();
            sysRoleLimit.setRoleId(roleId);
            sysRoleLimit.setLimitType(RoleLimitTypeEnum.MENU_OPTIONS.getCode());
            sysRoleLimit.setBusinessId(menuOptionsId);
            roleLimitList.add(sysRoleLimit);
        }

        return new MenuAndOptionsDTO(roleMenuList, roleOptionsList, roleLimitList);
    }

}
